<?php
/**
 *      [cdvphp!] (C)2012 - 2099 www.cdvphp.com
 *      框架核心类: 系统初始化, 路由分发, DB操作, 安全控制
 *
 *      $Id: core.php 2012-10-21 11:33:38 fanjiapeng $
 */
define('IN_CORE', TRUE);

class class_core {
	
	// 全局配置
	protected $config = array();

	// $_G 数组的映射
	protected $var = array();

	// 全局清理
	protected $globalvar = array(
		'GLOBALS' => 1,
		'_GET' => 1,
		'_POST' => 1,
		'_REQUEST' => 1,
		'_COOKIE' => 1,
		'_SERVER' => 1,
		'_FILES' => 1,
		'_SESSION' => 1
	);

	static private $_instance = NULL;

	// 建立唯一进程, 有且只有一个, 为了不影响程序运行, 不重新实例化.
	static function _get_instance($dispatch = TRUE) {
		self::$_instance === NULL && self::$_instance = new class_core($dispatch);
	}

	// 预处理入口
	private function __construct($dispatch) {

		// 加载配置文件、(蜘蛛、负载)检查
		$this->_config_sec_func();
		// 定义全局变量、常量
		$this->_set();

		// 输入信息组合
		$this->_input();
		// 输出信息组合
		$this->_output();

		// autoload
		$this->_spl_autoload();
		
		// URL路由
		$this->_url_router();

		// 类实例化函数, 自动载入类定义文件, 路由分发
		$dispatch && $this->_dispatch();
	}
	
	// 加载配置文件
	private function _config_sec_func() {
		// 开发者自定义配置文件
		require (ROOT_PATH. './config_inc.php');
		if(empty($_config)) exit('config_not_found');

		// 核心函数加载一次
		if(!defined('IN_FUNCTION')) require(FRAMEWORK_PATH. './function/function_core.php');

		// 如果开发者自定义函数库存在, 则加载
		if(file_exists(ROOT_PATH. './bootstrap.php')) require(ROOT_PATH. './bootstrap.php');

		// 合并配置文件
		$this->config = multimerge(config::instance(), $_config);

		// 搜索引擎蜘蛛判断
		($this->config['security']['robot'] && checkrobot()) && $this->_refuse_robot();

		// 负载判断
		if($this->config['security']['loadctrl'] > 0 && substr(PHP_OS, 0, 3) != 'WIN') {
			if($fp = @fopen('/proc/loadavg', 'r')) {
				list($loadaverage) = explode(' ', fread($fp, 6));
				fclose($fp);
				if($loadaverage > $this->config['security']['loadctrl']) {
					header("HTTP/1.0 503 Service Unavailable");
					include FRAMEWORK_PATH.'./include/serverbusy.htm';
					exit();
				}
			}
		}
	}
	
	// 定义PHP环境信息常量和全局变量 $_G
	private function _set() {

		// 如果是调试模式，打开警告输出
		$this->config['php']['error'] ? error_reporting(E_ALL & ~E_NOTICE) : error_reporting(0);

		// debug_tree, 用于Framework System Error
		if($this->config['system']['debug']) define('SYSTEM_DEBUG', TRUE);

		// 是否强制设置魔术方法
		if($this->config['php']['version'] && PHP_VERSION < '5.3.0' && get_magic_quotes_runtime() > 0) set_magic_quotes_runtime(0);

		// 检查PHP.ini 配置文件memory_limit大小
		if($_config['php']['memory_limit'] && function_exists('ini_get')) {
			$memorylimit = @ini_get('memory_limit');
			if($memorylimit && return_bytes($memorylimit) < 33554432 && function_exists('ini_set')) {
				ini_set('memory_limit', '128m');
			}
		}
		
		// PHP.ini是否自动开启过滤机制
		define('MAGIC_QUOTES_GPC', PHP_VERSION < '5.3.0' && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc());

		// 设置时区
		$this->_timezone_set($this->config['php']['timezone']);

		// 数据清理
		foreach ($GLOBALS as $key => & $value) {
			if (!isset($this->globalvar[$key])) {
				$GLOBALS[$key] = null; unset($GLOBALS[$key]);
			}
		}

		global $_G;
		$_G = array(
			'timestamp' => time(),
			'clientip' => $this->config['php']['client_ip'] ? $this->_get_client_ip() : $_SERVER['REMOTE_ADDR'],
			'referer' => & $_SERVER['HTTP_REFERER'],
			'charset' => $this->config['output']['charset'],

			'siteurl' => & $_SERVER['REQUEST_URI'],
			'basescript' => CURSCRIPT,

			'pathinfo'	   => array(),
			'config' => & $this->config,

			'cookie' => array(),
			'lang'	 => array(),

			'class' => array()
		);

		$this->var = & $_G;
	}
	
	/**
	 * 禁止对全局变量注入
	 * slashes 处理
	 * cookie 处理（去掉cookie前缀）
	 * 将 $_GET 与 $_POST 合并
	 *
	*/
	private function _input() {

		if (isset($_GET['GLOBALS']) || isset($_POST['GLOBALS']) || isset($_COOKIE['GLOBALS']) || isset($_FILES['GLOBALS'])) {
			system_error('request_tainting');
		}

		// if(!MAGIC_QUOTES_GPC) {
		// 	$_GET = $_GET ? daddslashes($_GET) : array();
		// 	$_POST = $_POST ? daddslashes($_POST) : array();
		// 	$_COOKIE = $_COOKIE ? daddslashes($_COOKIE) : array();
		// 	$_FILES = $_FILES ? daddslashes($_FILES) : array();
		// }

		if($this->config['cookie']['status']) {
			$prelength = strlen($this->config['cookie']['cookiepre']);
			foreach($_COOKIE as $key => $val) {
				if(substr($key, 0, $prelength) == $this->config['cookie']['cookiepre']) {
					$this->var['cookie'][substr($key, $prelength)] = $val;
				}
			}
		}

		if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST)) {
			$_GET = array_merge($_GET, $_POST);
		}

		foreach($_GET as $k => & $v) {
			$this->var['gp_'.$k] = & $v;
		}
	}

	/**
	 * 输出处理
	 * GET 参数跨站检测
	 * 防页面刷新
	 * gzip处理
	 * 字符集处理
	 *
	*/
	private function _output() {

		if($this->config['security']['urlxssdefend'] && $_SERVER['REQUEST_METHOD'] == 'GET' && isset($_SERVER['REQUEST_URI'])) {
			$this->_xss_check();
		}

		if($this->config['security']['attackevasive']) {
			require(FRAMEWORK_PATH. './class/security.php');
			class_security::instance();
		}
		
		// 是否需要PHP实现gzip压缩
		if($_config['output']['gzip'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === false) {
			$this->config['output']['gzip'] = false;
		}

		ob_start($this->config['output']['gzip'] && function_exists('ob_gzhandler') ? 'ob_gzhandler' : null);

		if($this->config['output']['forceheader']) {
			header('Content-Type: text/html; charset='. $this->config['output']['charset']);
		}
	}
	
	// URL路由
	private function _url_router() {;
		if($this->config['system']['url_router'] && isset($_SERVER['REQUEST_URI'])) {
			$this->var['pathinfo'] = explode('/', trim($_SERVER['REQUEST_URI'], '/'));

			// 兼容格式 index.php/main/index
			if(isset($this->var['pathinfo'][0]) && substr($this->var['pathinfo'][0], -4) == '.php') array_shift($this->var['pathinfo']);

			// 兼容格式 /main/index?page=1 /main?page=1
			$this->var["gp_{$this->config['system']['url_controller']}"] = (isset($this->var['pathinfo'][0]) && $this->var['pathinfo'][0]) ? (($int_find = strpos($this->var['pathinfo'][0], '?')) > 0 ? substr($this->var['pathinfo'][0], 0, $int_find) : $this->var['pathinfo'][0]) : $this->config['system']['default_controller'];

			$this->var["gp_{$this->config['system']['url_action']}"]     = (isset($this->var['pathinfo'][1]) && $this->var['pathinfo'][1]) ? 
				(($int_find = strpos($this->var['pathinfo'][1], '?')) > 0 ? substr($this->var['pathinfo'][1], 0, $int_find) : $this->var['pathinfo'][1]) : $this->config['system']['default_action'];
			
			$this->var['pathinfo'] = array_slice($this->var['pathinfo'], 2);
		}
	}
	
	// 类实例化函数, 自动载入类定义文件, 路由分发
	private function _dispatch() {
		// 构造执行路由
		$control_name = isset($this->var["gp_{$this->config['system']['url_controller']}"]) ? 
			$this->var["gp_{$this->config['system']['url_controller']}"] : $this->config['system']['default_controller'];
		$action_name = (isset($this->var["gp_{$this->config['system']['url_action']}"]) ? 
			$this->var["gp_{$this->config['system']['url_action']}"] : $this->config['system']['default_action']). '_action';
		
		// 检查类名称是否正确，以保证类定义文件载入的安全性
		if(preg_match('/[^a-zA-Z0-9\-_]/i', $control_name. $action_name)) system_error('require_class_error');

		// 加载文件
		$str_temp = ROOT_PATH. "./{$this->config['system']['controller_path']}/"._dir_classname($control_name).".php";
		if( TRUE == @is_readable($str_temp)) {
			require($str_temp);
		} else {
			system_error('require_control');
		}

		if(!class_exists($control_name, false) || interface_exists($control_name, false)) {
			system_error('require_control_class');
		}

		// 检查是否该类已经实例化，直接返回已实例对象，避免再次实例化
			$str_temp = md5($str_temp);
			if(!isset($this->var['class'][$str_temp])) {
				// 实例化对象
				
				$this->var['class'][$str_temp] = new $control_name();
			}

		if(!is_object($this->var['class'][$str_temp]) || !method_exists($this->var['class'][$str_temp], $action_name)){
			system_error('dispatcher_error');
		}

		// 路由并执行用户代码
		$this->var['class'][$str_temp]->{$action_name}();

		unset($control_name, $action_name, $str_temp);
	}

	// 类自动加载
	private function _spl_autoload() {
		spl_autoload_extensions('.php');
		spl_autoload_register(array($this, '_autoload'));
	}
	
	// 理想化: 锁定到框架class目录, 开发者library、control、model目录
	// 现实化: 所有位于根目录、框架目录下所有* 
	private function _autoload($str_classname = '') {
		$str_load_classname = '';
		if($str_classname) {
			$str_load_classname = _dir_classname($str_classname);
			spl_autoload(FRAMEWORK_PATH. './'. $str_load_classname);
			spl_autoload(ROOT_PATH. './'. $str_load_classname);
		}
	}
	
	// 禁止机器人访问
	private function _refuse_robot() {
		exit(header("HTTP/1.1 403 Forbidden"));
	}

	/**
	 * GET 参数跨站检测
	 *
	 * 增加对 CONTENT-TRANSFER-ENCODING 代码的检测 (IE MHTML 漏洞)
	 */
	private function _xss_check() {
		$temp = strtoupper(urldecode(urldecode($_SERVER['REQUEST_URI'])));
		if(strpos($temp, '<') !== false || strpos($temp, '"') !== false || strpos($temp, 'CONTENT-TRANSFER-ENCODING') !== false) {
			system_error('request_tainting');
		}

		return true;
	}

	/**
	* 设置时区
	* @param $timeoffset - 时区数值
	* @return 无
	*/
	private function _timezone_set($timeoffset = 0) {
		if(function_exists('date_default_timezone_set')) {
			date_default_timezone_set('Etc/GMT'.($timeoffset > 0 ? '-' : '+').(abs($timeoffset)));
		}
	}
	
	// 获取客户端IP
	private function _get_client_ip() {
		$ip = $_SERVER['REMOTE_ADDR'];
		if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
			$ip = $_SERVER['HTTP_CLIENT_IP'];
		} elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
			foreach ($matches[0] AS $xip) {
				if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
					$ip = $xip;
					break;
				}
			}
		}

		return $ip;
	}

	private function __clone() {}
}

/**
 * 初始化数据库类，同时自动选择主从数据库
 */
class db_mysql
{
	public $querynum 	= 0;
	
	public $curlink		= NULL;
	public $links 		= array();
	public $version 	= array();

	public $config 		= array();

	function set_config($config) {
		$this->config = & $config;
	}

	function connect($serverid = 1, $pconnect = 0) {

		if(empty($this->config) || empty($this->config[$serverid])) {
			$this->halt('config_db_not_found');
		}
		
		$this->links[$serverid] = $this->_dbconnect(
			$this->config[$serverid]['dbhost'],
			$this->config[$serverid]['dbuser'],
			$this->config[$serverid]['dbpw'],
			$this->config[$serverid]['dbcharset'],
			$this->config[$serverid]['dbname'],
			$pconnect ? $pconnect : $this->config[$serverid]['pconnect'],
			$serverid
		);
	}

	function _dbconnect($dbhost, $dbuser, $dbpw, $dbcharset, $dbname, $pconnect, $serverid) {
		$link = null; $mysql_version = '';
		$func = empty($pconnect) ? 'mysql_connect' : 'mysql_pconnect';
		if(!$link = @$func($dbhost, $dbuser, $dbpw, 1)) {
			$this->halt('notconnect');
		} else {
			$this->curlink = $link;
			if(($mysql_version = $this->version($serverid)) > '4.1') {
				$serverset = $dbcharset ? 'character_set_connection='.$dbcharset.', character_set_results='.$dbcharset.', character_set_client=binary' : '';
				$serverset .= $mysql_version > '5.0.1' ? ((empty($serverset) ? '' : ',').'sql_mode=\'\'') : '';
				$serverset && mysql_query("SET $serverset", $link);
			}
			$dbname && @mysql_select_db($dbname, $link);
		}

		return $link;
	}

	function table_name($tablename) {
		return $this->config[array_search($this->curlink, $this->links)]['tablepre']. $tablename;
	}

	function select_db($dbname) {
		return mysql_select_db($dbname, $this->curlink);
	}

	function fetch_array($query, $result_type = MYSQL_ASSOC) {
		return mysql_fetch_array($query, $result_type);
	}

	function fetch_first($sql) {
		return $this->fetch_array($this->query($sql));
	}

	function result_first($sql) {
		return $this->result($this->query($sql), 0);
	}

	function query($sql, $type = '') {
		 
		$func = $type == 'UNBUFFERED' && @function_exists('mysql_unbuffered_query') ?
			'mysql_unbuffered_query' : 'mysql_query';
		if(!($query = $func($sql, $this->curlink))) {
			if(in_array($this->errno(), array(2006, 2013)) && substr($type, 0, 5) != 'RETRY') {
				$this->connect(array_search($this->curlink, $this->links));
				return $this->query($sql, 'RETRY'.$type);
			}

			if($type != 'SILENT' && substr($type, 5) != 'SILENT') {
				$this->halt('query_error', $sql);
			}
		}

		$this->querynum++;

		return $query;
	}

	function affected_rows() {
		return mysql_affected_rows($this->curlink);
	}

	function error($curlink = '') {
		return mysql_error($curlink ? $curlink : ($this->curlink ? $this->curlink : ''));
	}

	function errno($curlink = '') {
		return intval(mysql_errno($curlink ? $curlink : ($this->curlink ? $this->curlink : '')));
	}

	function result($query, $row = 0) {
		$query = @mysql_result($query, $row);
		return $query;
	}

	function num_rows($query) {
		$query = mysql_num_rows($query);
		return $query;
	}

	function num_fields($query) {
		return mysql_num_fields($query);
	}

	function free_result($query) {
		return mysql_free_result($query);
	}

	function insert_id() {
		return ($id = mysql_insert_id($this->curlink)) >= 0 ? $id : $this->result($this->query("SELECT last_insert_id()"), 0);
	}

	function fetch_row($query) {
		$query = mysql_fetch_row($query);
		return $query;
	}

	function fetch_fields($query) {
		return mysql_fetch_field($query);
	}

	function version($serverid = 1) {
		if(!isset($this->version[$serverid])) {
			$this->version[$serverid] = mysql_get_server_info($this->curlink);
		}
		return $this->version[$serverid];
	}

	function close($curlink = '') {
		return mysql_close($curlink ? $curlink : $this->curlink);
	}

	function halt($message = '', $sql = '') {
		require FRAMEWORK_PATH . './class/error.php';
		class_error::db_error($message, $sql);
	}
}

class db
{
	static private $links	 = array();
	static private $db		 = NULL;
	static private $masterid = 0;
	static private $slaveid  = 0;

	static function _select_link($sql = '') {
		if(!is_string($sql)) return FALSE;
		if(isset(self::$links['slave']) && is_string($sql) && strtoupper(substr($sql, 0 , 6)) == 'SELECT') {
			self::$db->curlink = self::$links['slave'];
		} else {
			self::$db->curlink = isset(self::$links['master']) ? self::$links['master'] : self::$links['slave'];
		}
	}

	static function _execute($cmd, $arg1 = '', $arg2 = '') {
		self::_select_link($arg1);
		$res = self::$db->$cmd($arg1, $arg2);
		return $res;
	}

	static function & link($dbtype = 'all', $serverid = 1, $pconnect = FALSE, $self = FALSE) {
		return self::isobject($dbtype = 'all', $serverid = 1, $pconnect = FALSE, $self = FALSE);
	}

	// master 主库，slave 从库 , all 同时连接主库从库
	static function & isobject($dbtype = 'all', $serverid = 1, $pconnect = FALSE, $self = FALSE) {
		if(!in_array($dbtype, array('master', 'slave', 'all'))) {
			die('connect_dbtype_failed');
		}

		if($dbtype == 'all' && $self == FALSE) {
			self::isobject('master', $serverid, $pconnect, TRUE);
			self::isobject('slave', $serverid, $pconnect, TRUE);
			return FALSE;
		}

		if(!isset(self::$links[$dbtype])) {
			self::_object($dbtype, $serverid, $pconnect);
		} elseif(!@mysql_ping(self::$links[$dbtype][$serverid])) {
			@mysql_close(self::$links[$dbtype]);
			self::_object($dbtype, $serverid, $pconnect);
		}

		return self::$links[$dbtype];
	}

	static function & _object($dbtype = 'master', $serverid = 1, $pconnect = FALSE) {
		global $_G;

		self::$db = new db_mysql();
		self::$db->set_config($_G['config']['db']);

		if($dbtype == 'slave') {
			$sid = $serverid > 1 ? $serverid : array_rand($_G['config']['db']['slave']);
			self::$slaveid = $serverid = 1000 + $sid;
			self::$db->config[$serverid] = & $_G['config']['db']['slave'][$sid];

			unset(self::$db->config['slave']);
			isset(self::$links['master']) && self::$db->links[self::$masterid] = self::$links['master'];
		} else {
			if(isset(self::$links['slave'])) {
				self::$db->links[self::$slaveid] = self::$links['slave'];
			}

			self::$masterid = $serverid;
		}

		self::$db->connect($serverid, $pconnect);
		self::$links[$dbtype] = self::$db->curlink;
	}

	static function getdb() {
		return self::$db;
	}

	static function table($table) {
		return db::_execute('table_name', $table);
	}

	static function delete($table, $condition, $limit = 0, $unbuffered = true) {
		if(empty($condition)) {
			$where = '1';
		} elseif(is_array($condition)) {
			$where = db::implode_field_value($condition, ' AND ');
		} else {
			$where = $condition;
		}
		$sql = "DELETE FROM ".db::table($table)." WHERE $where ".($limit ? "LIMIT $limit" : '');
		return db::query($sql, ($unbuffered ? 'UNBUFFERED' : ''));
	}

	static function insert($table, $data, $return_insert_id = false, $replace = false, $silent = false) {

		$sql = db::implode_field_value($data);

		$cmd = $replace ? 'REPLACE INTO' : 'INSERT INTO';

		$table = db::table($table);
		$silent = $silent ? 'SILENT' : '';

		$return = db::query("$cmd $table SET $sql", $silent);

		return $return_insert_id ? db::insert_id() : $return;

	}

	static function update($table, $data, $condition, $unbuffered = false, $low_priority = false) {
		$sql = db::implode_field_value($data);
		$cmd = "UPDATE ".($low_priority ? 'LOW_PRIORITY' : '');
		$table = db::table($table);
		$where = '';
		if(empty($condition)) {
			$where = '1';
		} elseif(is_array($condition)) {
			$where = db::implode_field_value($condition, ' AND ');
		} else {
			$where = $condition;
		}
		$res = db::query("$cmd $table SET $sql WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
		return $res;
	}
	
	// 唯一一个非常特殊的函数，可以指定主库进行查询操作
	static function get_row($sql, $master = false, $result_type = MYSQL_ASSOC) {
		if($master && isset(self::$links['master'])) self::$db->curlink = self::$links['master'];
		return self::$db->fetch_array(self::$db->query($sql), $result_type);
	}

	static function implode_field_value($array, $glue = ',') {
		$sql = $comma = '';
		foreach ($array as $k => $v) {
			//这边进行字符的转义，可以安全用于mysql_query
			$v     = mysql_escape_string($v);
			$sql   .= $comma."`$k`='$v'";
			$comma = $glue;
		}
		return $sql;
	}

	static function implode_line_value($array, $glue = ',') {
		return implode($glue, $array);
	}

	static function all($table, $data, $condition = '', $limit = 0, $perpage = 100, $key = '', $unbuffered = false) {
		$sql = db::implode_line_value($data);
		$table = db::table($table);
		
		$where = '';
		if(empty($condition)) {
			$where = '1';
		} elseif(is_array($condition)) {
			$where = db::implode_field_value($condition, ' AND ');
		} else {
			$where = $condition;
		}

		$where .= ' LIMIT '.intval($limit < 1 ? 0 : $limit).', '.intval($perpage).'';

		$userlist = $data = array();
		$query = db::query("SELECT SQL_CALC_FOUND_ROWS $sql FROM $table WHERE $where", $unbuffered ? 'UNBUFFERED' : '');
		$res['count'] = db::result(db::query('SELECT FOUND_ROWS()'));
		while ($data  = mysql_fetch_assoc($query)) {
		//while ($data  = db::fetch($query)) {
			if($key) {
				$res['data'][$data[$key]] = $data;
			} else {
				$res['data'][] = $data;
			}
		}

		return $res;
	}

	static function insert_id() {
		return db::_execute('insert_id');
	}

	static function fetch($resourceid, $type = MYSQL_ASSOC) {
		return db::_execute('fetch_array', $resourceid, $type);
	}

	static function fetch_first($sql) {
		return db::_execute('fetch_first', $sql);
	}

	static function result($resourceid, $row = 0) {
		return db::_execute('result', $resourceid, $row);
	}

	static function result_first($sql) {
		return db::_execute('result_first', $sql);
	}

	static function query($sql, $type = '') {
		db::checkquery($sql);
		return db::_execute('query', $sql, $type);
	}

	static function num_rows($resourceid) {
		return db::_execute('num_rows', $resourceid);
	}

	static function affected_rows() {
		return db::_execute('affected_rows');
	}

	static function free_result($query) {
		return db::_execute('free_result', $query);
	}

	static function error() {
		return db::_execute('error');
	}

	static function errno() {
		return db::_execute('errno');
	}

	static function close($curlink = '') {
		return db::_execute('close', $curlink);
	}

	static function checkquery($sql) {
		static $status = null, $checkcmd = array('SELECT', 'UPDATE', 'INSERT', 'REPLACE', 'DELETE');
		if($status === null) $status = getglobal('config/security/querysafe/status');
		if($status) {
			$cmd = trim(strtoupper(substr($sql, 0, strpos($sql, ' '))));
			if(in_array($cmd, $checkcmd)) {
				$test = db::_do_query_safe($sql);
				if($test < 1) db::_execute('halt', 'security_error', $sql);
			}
		}
		return true;
	}

	static function _do_query_safe($sql) {
		static $_CONFIG = null;
		if($_CONFIG === null) {
			$_CONFIG = getglobal('config/security/querysafe');
		}

		$sql = str_replace(array('\\\\', '\\\'', '\\"', '\'\''), '', $sql);
		$mark = $clean = '';
		if(strpos($sql, '/') === false && strpos($sql, '#') === false && strpos($sql, '-- ') === false) {
			$clean = preg_replace("/'(.+?)'/s", '', $sql);
		} else {
			$len = strlen($sql);
			$mark = $clean = '';
			for ($i = 0; $i <$len; $i++) {
				$str = $sql[$i];
				switch ($str) {
					case '\'':
						if(!$mark) {
							$mark = '\'';
							$clean .= $str;
						} elseif ($mark == '\'') {
							$mark = '';
						}
						break;
					case '/':
						if(empty($mark) && $sql[$i+1] == '*') {
							$mark = '/*';
							$clean .= $mark;
							$i++;
						} elseif($mark == '/*' && $sql[$i -1] == '*') {
							$mark = '';
							$clean .= '*';
						}
						break;
					case '#':
						if(empty($mark)) {
							$mark = $str;
							$clean .= $str;
						}
						break;
					case "\n":
						if($mark == '#' || $mark == '--') {
							$mark = '';
						}
						break;
					case '-':
						if(empty($mark)&& substr($sql, $i, 3) == '-- ') {
							$mark = '-- ';
							$clean .= $mark;
						}
						break;

					default:

						break;
				}
				$clean .= $mark ? '' : $str;
			}
		}

		$clean = preg_replace("/[^a-z0-9_\-\(\)#\*\/\"]+/is", "", strtolower($clean));

		if($_CONFIG['afullnote']) {
			$clean = str_replace('/**/','',$clean);
		}

		if(is_array($_CONFIG['dfunction'])) {
			foreach($_CONFIG['dfunction'] as $fun) {
				if(strpos($clean, $fun.'(') !== false) return '-1';
			}
		}

		if(is_array($_CONFIG['daction'])) {
			foreach($_CONFIG['daction'] as $action) {
				if(strpos($clean,$action) !== false) return '-3';
			}
		}

		if($_CONFIG['dlikehex'] && strpos($clean, 'like0x')) {
			return '-2';
		}

		if(is_array($_CONFIG['dnote'])) {
			foreach($_CONFIG['dnote'] as $note) {
				if(strpos($clean,$note) !== false) return '-4';
			}
		}

		return 1;
	}
}

// control继承model类、view类

class control 
{
	public  $model   = null;
	private $display = false;
	private $vars	 = array();

	public function __construct($auto_model = true, $auto_display = false) {
		$auto_model && $this->load_model();
		$this->display = $auto_display;
	}

	public function load_model($model_name = '') {
		$this->model = model($model_name ? $model_name : get_class($this), false);
	}

	public function assign($k, $v) {
		$this->vars[$k] = $v;
	}

	public function display($template_name = '') {
		extract($this->vars, EXTR_SKIP);
		include template($template_name ? $template_name : get_class($this));
	}

	public function __destruct() {
		(getglobal('config/system/view_auto_display') || $this->display) && $this->display();
	}
}

class config
{
	static public function instance() {

		$_config = array();

		$_config['db']['1']['dbhost'] 		= '127.0.0.1'; 	// 主机IP地址
		$_config['db']['1']['dbuser'] 		= 'root';  		// 用户名
		$_config['db']['1']['dbpw'] 		= '';			// 密码
		$_config['db']['1']['dbcharset'] 	= 'utf8'; 		// 数据库连接
		$_config['db']['1']['pconnect'] 	= '0'; 			// 是否使用超连接
		$_config['db']['1']['dbname'] 		= 'message';	// 数据库名字
		$_config['db']['1']['tablepre'] 	= 'cdv_'; 		// 表前缀

		$_config['db']['slave'][1]['dbhost'] 	= '127.0.0.1';
		$_config['db']['slave'][1]['dbuser'] 	= 'root';
		$_config['db']['slave'][1]['dbpw'] 		= '';
		$_config['db']['slave'][1]['dbcharset'] = 'utf8';
		$_config['db']['slave'][1]['pconnect'] 	= '0';
		$_config['db']['slave'][1]['dbname'] 	= 'message';
		$_config['db']['slave'][1]['tablepre'] 	= 'cdv_';
		
		// 页面输出设置
		$_config['output']['charset'] 			= 'utf-8';	// 页面字符集
		$_config['output']['forceheader']		= 0;		// 强制输出页面字符集，用于避免某些环境乱码
		$_config['output']['gzip'] 				= 0;		// 是否采用 Gzip 压缩输出
		$_config['output']['tplrefresh'] 		= 1;		// 模板自动刷新开关 0=关闭, 1=打开
		$_config['output']['language'] 			= 'zh_cn';	// 页面语言 zh_cn/zh_tw

		// COOKIE 设置
		$_config['cookie']['status']			= 1;		// 开启cookie机制
		$_config['cookie']['cookiepre'] 		= 'cdv_';	// COOKIE前缀
		$_config['cookie']['cookiedomain'] 		= '';		// COOKIE作用域
		$_config['cookie']['cookiepath'] 		= '/';		// COOKIE作用路径

		// 站点安全设置
		$_config['security']['authkey']             = 'cdvphp';  // 站点加密密钥
		$_config['security']['urlxssdefend']		= 1;         // 自身 URL XSS 防御
		$_config['security']['attackevasive']		= 0;         // CC 攻击防御 1|2|4|8
		$_config['security']['robot']        		= 0;		 // 搜索引擎蜘蛛判断
		$_config['security']['loadctrl']        	= 0;		 // 非windows+值大于0才会生效, Linux负载判断,如果系统负载超过此值,提示有好信息

		// 防止SQL注入攻击设置
		$_config['security']['querysafe']['status']     = 1;    // 是否开启SQL安全检测，可自动预防SQL注入攻击
		$_config['security']['querysafe']['dfunction']	= array('load_file','hex','substring','if','ord','char');
		$_config['security']['querysafe']['daction']	= array('intooutfile','intodumpfile','unionselect','(select', 'unionall', 'uniondistinct');
		$_config['security']['querysafe']['dnote']		= array('/*','*/','#','--','"');
		$_config['security']['querysafe']['dlikehex']	= 1;
		$_config['security']['querysafe']['afullnote']	= 0;

		// 框架核心设置
		$_config['system']['default_controller'] = 'main';  // 默认control文件名字
		$_config['system']['default_action']     = 'index'; // 默认方法
		$_config['system']['url_controller']     = 'c';  	// control名
		$_config['system']['url_action']         = 'a';	 	// action 名
		$_config['system']['view_auto_display']  = 0;    	// 模板自动加载关闭
		$_config['system']['debug']         	 = 0;    	// 调试模式将输出所有错误信息 1开启 0关闭
		$_config['system']['controller_path']    = 'control'; // control文件夹名字
		$_config['system']['model_path']         = 'model';   // model文件夹名字
		$_config['system']['view_path']          = 'view';    // view文件夹名字
		$_config['system']['url_router']         = 0;  		  // 1开启URL路由 0关闭
		$_config['system']['template_suffix']    = 'html';    // 设置模板后缀


		// 框架其它设置 (1开启 0关闭)
		$_config['php']['memory_limit']   = 0;    // 设置PHP最小可用内存, 服务器不可能小于128M, 默认就是128M
		$_config['php']['version']        = 0;    // set_magic_quotes_runtime(0)
		$_config['php']['error']          = 0;    // 控制php.ini error_reporting(*); 1开启 0关闭
		$_config['php']['timezone']       = '+8'; // 时区设置 东八区
		$_config['php']['client_ip']	  = 0;	  // 强制判断与获取客户端IP

		return $_config;
	}
}
?>
